﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MvCamCtrl.NET;
using System.Threading;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
using MvCamCtrl.NET.CameraParams;
using System.Runtime.InteropServices;
using HalconDotNet;
using System.IO;

namespace SSVisionCom
{
    public class HikVisionCamera
    {
        public CCamera m_MyCamera = new CCamera();
        private static List<CCameraInfo> m_ltDeviceList = new List<CCameraInfo>();

        bool m_bGrabbing = false;
        bool m_bRecord = false;
        Thread m_hReceiveThread = null;

        // ch:用于从驱动获取图像的缓存 | en:Buffer for getting image from driver
        private static Object BufForDriverLock = new Object();
        private CImage m_pcImgForDriver;        // 图像信息
        private CFrameSpecInfo m_pcImgSpecInfo; // 图像的水印信息
        private CSaveImageParam m_pcSaveParam = new CSaveImageParam(); // 保存到缓存的参数信息
        public Bitmap m_pcBitmap = null;
        PixelFormat m_enBitmapPixelFormat = PixelFormat.DontCare;
        private bool m_bRenderByBitmap = false;
        private Graphics m_pcGraphic = null;

        private UInt32 m_nCurWidth = 0;
        private UInt32 m_nCurHeight = 0;
        private MvGvspPixelType m_emPixelType = MvGvspPixelType.PixelType_Gvsp_Mono8;
        public PictureBox pictureBox1 = new PictureBox();

        public static List<CameraDev> CameraList = new List<CameraDev>();

        /// <summary>
        /// 初始化相机列表
        /// </summary>
        public static void InitCameraList()
        {
            System.GC.Collect();
            m_ltDeviceList.Clear();
            CameraList.Clear();
            try
            {
                int nRet = CSystem.EnumDevices(CSystem.MV_GIGE_DEVICE | CSystem.MV_USB_DEVICE, ref m_ltDeviceList);
                if (0 != nRet)
                {
                    MessageBox.Show("获取相机列表失败", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }
                for (int i = 0; i < m_ltDeviceList.Count; i++)
                {
                    if (m_ltDeviceList[i].nTLayerType == CSystem.MV_GIGE_DEVICE)
                    {
                        CGigECameraInfo gigeInfo = (CGigECameraInfo)m_ltDeviceList[i];

                        CameraDev cameraDev = new CameraDev();

                        if (gigeInfo.UserDefinedName != "")
                        {
                            cameraDev.Device_Type = "GigE Vision";
                            cameraDev.Dev_UserDefinedName = gigeInfo.UserDefinedName;
                            cameraDev.Dev_chModelName = gigeInfo.chModelName;
                            cameraDev.Dev_Serial = gigeInfo.chSerialNumber;
                            CameraList.Add(cameraDev);
                        }
                        else
                        {
                            cameraDev.Device_Type = "GigE Vision";
                            cameraDev.Dev_chManufacturerName = gigeInfo.chManufacturerName;
                            cameraDev.Dev_chModelName = gigeInfo.chModelName;
                            cameraDev.Dev_Serial = gigeInfo.chSerialNumber;
                            CameraList.Add(cameraDev);

                        }
                    }
                    else if (m_ltDeviceList[i].nTLayerType == CSystem.MV_USB_DEVICE)
                    {
                        CUSBCameraInfo usbInfo = (CUSBCameraInfo)m_ltDeviceList[i];
                        CameraDev cameraDev = new CameraDev();
                        if (usbInfo.UserDefinedName != "")
                        {
                            cameraDev.Device_Type = "USB3 Vision";
                            cameraDev.Dev_UserDefinedName = usbInfo.UserDefinedName;
                            cameraDev.Dev_chModelName = usbInfo.chModelName;
                            cameraDev.Dev_Serial = usbInfo.chSerialNumber;
                            CameraList.Add(cameraDev);

                        }
                        else
                        {
                            cameraDev.Device_Type = "USB3 Vision";
                            cameraDev.Dev_chManufacturerName = usbInfo.chManufacturerName;
                            cameraDev.Dev_chModelName = usbInfo.chModelName;
                            cameraDev.Dev_Serial = usbInfo.chSerialNumber;
                            CameraList.Add(cameraDev);
                        }
                    }
                }
            }
            catch
            {
                MessageBox.Show("初始化相机列表失败");
            }
        }
        /// <summary>
        /// 打开指定设备
        /// </summary>
        public int Open_Dev(string SerialNumber)
        {
            int OperationResult = 0;
            if (CameraList.Count > 0)
            {
                //获取目标设备在当前列表的位置
                int CameraIndex = -1;
                for (int i = 0; i < CameraList.Count; i++)
                {
                    if (SerialNumber == CameraList[i].Dev_Serial)
                    {
                        CameraIndex = i;
                        break;
                    }
                }
                if (CameraIndex > -1)
                {
                    // ch:获取选择的设备信息 | en:Get selected device information
                    CCameraInfo device = m_ltDeviceList[CameraIndex];

                    // ch:打开设备 | en:Open device
                    if (null == m_MyCamera)
                    {
                        m_MyCamera = new CCamera();
                        if (null == m_MyCamera)
                        {
                            OperationResult = 1;
                            return OperationResult;
                        }
                    }

                    int nRet = m_MyCamera.CreateHandle(ref device);
                    if (CErrorDefine.MV_OK != nRet)
                    {
                        OperationResult = 2;
                        return OperationResult;
                    }

                    nRet = m_MyCamera.OpenDevice();
                    if (CErrorDefine.MV_OK != nRet)
                    {
                        m_MyCamera.DestroyHandle();
                        MessageBox.Show("打开设备异常", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        OperationResult = 3;
                        return OperationResult;
                    }

                    // ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
                    if (device.nTLayerType == CSystem.MV_GIGE_DEVICE)
                    {
                        int nPacketSize = m_MyCamera.GIGE_GetOptimalPacketSize();
                        if (nPacketSize > 0)
                        {
                            nRet = m_MyCamera.SetIntValue("GevSCPSPacketSize", (uint)nPacketSize);
                            if (nRet != CErrorDefine.MV_OK)
                            {
                                MessageBox.Show("设置网络数据包大小异常", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                            }
                        }
                    }

                    // ch:前置配置 | en:pre-operation
                    nRet = NecessaryOperBeforeGrab();
                    if (CErrorDefine.MV_OK != nRet)
                    {
                        OperationResult = 4;
                        return OperationResult;
                    }

                    m_MyCamera.SetEnumValue("TriggerMode", (uint)MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_OFF);

                    nRet = m_MyCamera.StartGrabbing();
                    if (CErrorDefine.MV_OK != nRet)
                    {
                        m_bGrabbing = false;
                        m_hReceiveThread.Join();
                        MessageBox.Show("打开数据量失败", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        OperationResult = 5;
                        return OperationResult;
                    }
                }
                else
                {
                    OperationResult = 6;
                }

                return OperationResult;

            }
            else
            {
                OperationResult = 6;
                return OperationResult;
            }

        }

        public Bitmap GetImageBitMap()
        {
            CFrameout pcFrameInfo = new CFrameout();
            CPixelConvertParam pcConvertParam = new CPixelConvertParam();
            CDisplayFrameInfo pcDisplayInfo = new CDisplayFrameInfo();
            int nRet = m_MyCamera.GetImageBuffer(ref pcFrameInfo, 1000);
            if (CErrorDefine.MV_OK == nRet)
            {

                m_pcBitmap = m_MyCamera.ImageToBitmap(ref pcFrameInfo);
            }
            else
            {
                OpearationTxt.WriteIni("Log",DateTime.Now.ToString(),"相机拍照失败",Directory.GetCurrentDirectory()+@"\RunLog.ini");
            }
            try
            {
               
               if (pcFrameInfo.Image != null) m_MyCamera.FreeImageBuffer(ref pcFrameInfo);
            }
            catch
            {
                OpearationTxt.WriteIni("Log", DateTime.Now.ToString(), "相机清除缓存失败", Directory.GetCurrentDirectory() + @"\RunLog.ini");
            }
           
            return m_pcBitmap;
        }


        private Int32 NecessaryOperBeforeGrab()
        {
            // ch:取图像宽 | en:Get Iamge Width
            CIntValue pcWidth = new CIntValue();
            int nRet = m_MyCamera.GetIntValue("Width", ref pcWidth);
            if (CErrorDefine.MV_OK != nRet)
            {
                MessageBox.Show("获取图像宽度异常", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return nRet;
            }
            m_nCurWidth = (UInt32)pcWidth.CurValue;


            // ch:取图像高 | en:Get Iamge Height
            CIntValue pcHeight = new CIntValue();
            nRet = m_MyCamera.GetIntValue("Height", ref pcHeight);
            if (CErrorDefine.MV_OK != nRet)
            {
                MessageBox.Show("获取图像高度异常", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return nRet;
            }
            m_nCurHeight = (UInt32)pcHeight.CurValue;

            // ch:取像素格式 | en:Get Pixel Format
            CEnumValue pcPixelFormat = new CEnumValue();
            nRet = m_MyCamera.GetEnumValue("PixelFormat", ref pcPixelFormat);
            if (CErrorDefine.MV_OK != nRet)
            {
                MessageBox.Show("获取图像像素格式异常", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return nRet;
            }
            m_emPixelType = (MvGvspPixelType)pcPixelFormat.CurValue;



            // ch:设置bitmap像素格式
            if ((Int32)MvGvspPixelType.PixelType_Gvsp_Undefined == (Int32)pcPixelFormat.CurValue)
            {
                return CErrorDefine.MV_E_UNKNOW;
            }
            else if (IsMonoData((MvGvspPixelType)pcPixelFormat.CurValue))
            {
                m_enBitmapPixelFormat = PixelFormat.Format8bppIndexed;
            }
            else
            {
                m_enBitmapPixelFormat = PixelFormat.Format24bppRgb;
            }

            if (null != m_pcBitmap)
            {
                m_pcBitmap.Dispose();
                m_pcBitmap = null;
            }
            m_pcBitmap = new Bitmap((Int32)pcWidth.CurValue, (Int32)pcHeight.CurValue, m_enBitmapPixelFormat);

            // ch:Mono8格式，设置为标准调色板 | en:Set Standard Palette in Mono8 Format
            if (PixelFormat.Format8bppIndexed == m_enBitmapPixelFormat)
            {
                ColorPalette palette = m_pcBitmap.Palette;
                for (int i = 0; i < palette.Entries.Length; i++)
                {
                    palette.Entries[i] = Color.FromArgb(i, i, i);
                }
                m_pcBitmap.Palette = palette;
            }


            return CErrorDefine.MV_OK;
        }
        private Boolean IsMonoData(MvGvspPixelType enPixelType)
        {
            switch (enPixelType)
            {
                case MvGvspPixelType.PixelType_Gvsp_Mono8:
                case MvGvspPixelType.PixelType_Gvsp_Mono8_Signed:
                case MvGvspPixelType.PixelType_Gvsp_Mono10:
                case MvGvspPixelType.PixelType_Gvsp_Mono10_Packed:
                case MvGvspPixelType.PixelType_Gvsp_Mono12:
                case MvGvspPixelType.PixelType_Gvsp_Mono12_Packed:
                case MvGvspPixelType.PixelType_Gvsp_Mono14:
                case MvGvspPixelType.PixelType_Gvsp_Mono16:
                case MvGvspPixelType.PixelType_Gvsp_HB_Mono8:
                case MvGvspPixelType.PixelType_Gvsp_HB_Mono10:
                case MvGvspPixelType.PixelType_Gvsp_HB_Mono10_Packed:
                case MvGvspPixelType.PixelType_Gvsp_HB_Mono12:
                case MvGvspPixelType.PixelType_Gvsp_HB_Mono12_Packed:
                case MvGvspPixelType.PixelType_Gvsp_HB_Mono16:
                    return true;
                default:
                    return false;
            }
        }

        public void ReceiveThreadProcess()
        {
            int nRet = CErrorDefine.MV_OK;

            while (m_bGrabbing)
            {
                CFrameout pcFrameInfo = new CFrameout();
                CDisplayFrameInfo pcDisplayInfo = new CDisplayFrameInfo();
                CPixelConvertParam pcConvertParam = new CPixelConvertParam();

                nRet = m_MyCamera.GetImageBuffer(ref pcFrameInfo, 1000);
                if (nRet == CErrorDefine.MV_OK)
                {
                    if (m_bRecord)
                    {
                        CInputFrameInfo pcInputFrameInfo = new CInputFrameInfo();
                        pcInputFrameInfo.InImage = pcFrameInfo.Image;
                        m_MyCamera.InputOneFrame(ref pcInputFrameInfo);
                    }

                    lock (BufForDriverLock)
                    {
                        m_pcImgForDriver = pcFrameInfo.Image.Clone() as CImage;
                        m_pcImgSpecInfo = pcFrameInfo.FrameSpec;
                    }

                    if (m_bRenderByBitmap)
                    {
                        Bitmap pcBitmap = m_MyCamera.ImageToBitmap(ref pcFrameInfo);
                        if (null != pcBitmap)
                        {
                            if (m_pcGraphic == null)
                            {
                                m_pcGraphic = pictureBox1.CreateGraphics();
                            }

                            Rectangle pcDstRect = new Rectangle(0, 0, pictureBox1.Width, pictureBox1.Height);
                            Rectangle pcSrcRect = new Rectangle(0, 0, pcBitmap.Width, pcBitmap.Height);
                            m_pcGraphic.DrawImage(pcBitmap, pcDstRect, pcSrcRect, GraphicsUnit.Pixel);
                            pcBitmap.Dispose();
                        }
                    }
                    else
                    {
                        pcDisplayInfo.WindowHandle = pictureBox1.Handle;
                        pcDisplayInfo.Image = pcFrameInfo.Image;
                        m_MyCamera.DisplayOneFrame(ref pcDisplayInfo);
                    }
                    m_MyCamera.FreeImageBuffer(ref pcFrameInfo);
                }
                else
                {

                    Thread.Sleep(1);
                }
            }
        }

        private Boolean IsMono(MvGvspPixelType enPixelType)
        {
            switch (enPixelType)
            {
                case MvGvspPixelType.PixelType_Gvsp_Mono1p:
                case MvGvspPixelType.PixelType_Gvsp_Mono2p:
                case MvGvspPixelType.PixelType_Gvsp_Mono4p:
                case MvGvspPixelType.PixelType_Gvsp_Mono8:
                case MvGvspPixelType.PixelType_Gvsp_Mono8_Signed:
                case MvGvspPixelType.PixelType_Gvsp_Mono10:
                case MvGvspPixelType.PixelType_Gvsp_Mono10_Packed:
                case MvGvspPixelType.PixelType_Gvsp_Mono12:
                case MvGvspPixelType.PixelType_Gvsp_Mono12_Packed:
                case MvGvspPixelType.PixelType_Gvsp_Mono14:
                case MvGvspPixelType.PixelType_Gvsp_Mono16:
                    return true;
                default:
                    return false;
            }
        }

        public void Close()
        {
            try
            {
                if (m_MyCamera != null)
                {
                    // ch:标志位设为false | en:Set flag bit false
                    if (m_hReceiveThread != null) m_hReceiveThread.Join();
                    m_bGrabbing = false;

                    // ch:停止采集 | en:Stop Grabbing
                    int nRet = m_MyCamera.StopGrabbing();
                    if (nRet != CErrorDefine.MV_OK)
                    {

                    }
                    // ch:关闭设备 | en:Close Device
                    m_MyCamera.CloseDevice();
                    m_MyCamera.DestroyHandle();
                }
            }
            catch
            {
                
            }
        }
    }
    public class CameraDev
    {
        public string Device_Type; //设备类型网口相机 or USB口相机
        public string Dev_Serial; //设备序列号；
        public string Dev_UserDefinedName; // 用户自定义名称
        public string Dev_chManufacturerName;//制造商名称
        public string Dev_chModelName;//设备型号
    }
    public class ImageConvert
    {
        public static void  Bitmap2HObjectS(Bitmap bmp, out HObject image)
        {
            try
            {
                Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
                BitmapData srcBmpData = bmp.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

                byte[] r = new byte[srcBmpData.Height * srcBmpData.Width];
                byte[] g = new byte[srcBmpData.Height * srcBmpData.Width];
                byte[] b = new byte[srcBmpData.Height * srcBmpData.Width];

                IntPtr ptr1 = Marshal.UnsafeAddrOfPinnedArrayElement(r, 0);
                IntPtr ptr2 = Marshal.UnsafeAddrOfPinnedArrayElement(g, 0);
                IntPtr ptr3 = Marshal.UnsafeAddrOfPinnedArrayElement(b, 0);

                unsafe
                {
                    byte* pIn = (byte*)(srcBmpData.Scan0.ToPointer());
                    for (int y = 0; y < srcBmpData.Height; y++)  //列扫描
                    {
                        for (int x = 0; x < srcBmpData.Width; x++)   //行扫描
                        {
                            int index = y * srcBmpData.Width + x;
                            r[index] = pIn[0];
                            g[index] = pIn[1];
                            b[index] = pIn[2];
                            pIn += 3;
                        }
                        pIn += srcBmpData.Stride - srcBmpData.Width * 3;
                    }
                }
                HOperatorSet.GenImage3(out image, "byte", srcBmpData.Width, srcBmpData.Height, new HTuple(ptr3), new HTuple(ptr2), new HTuple(ptr1));
                bmp.UnlockBits(srcBmpData);
            }
            catch (Exception)
            {
                image = null;
            }
        }
        public static Bitmap Honject2Bitmap(HObject hObject)
        {
            //获取图像尺寸
            HOperatorSet.GetImageSize(hObject, out HTuple width0, out HTuple height0);

            HOperatorSet.GetImageSize(hObject, out width0, out height0);
            //创建交错格式图像
            HOperatorSet.InterleaveChannels(hObject, out HObject InterImage, "rgb", 4 * width0, 0);
            //获取交错格式图像指针
            HOperatorSet.GetImagePointer1(InterImage, out HTuple Pointer, out HTuple type, out HTuple width, out HTuple height);
            IntPtr ptr = Pointer;
            //构建新Bitmap图像
            Bitmap bitmap = new Bitmap(width / 4, height, width, PixelFormat.Format24bppRgb, ptr);
            return bitmap;
        }


    }
        
}
